package com.superbit.web.servlet;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.superbit.core.constant.UserStatusConstant;
import com.superbit.core.entry.UserActivityInfo;
import com.superbit.core.entry.UserBaseInfo;
import com.superbit.core.exception.BusinessException;
import com.superbit.core.exception.ParamInvalidException;
import com.superbit.core.service.LoginService;
import com.superbit.core.service.UserRoleService;
import com.superbit.service.util.StringTools;
import com.superbit.utils.mailutil.EmailFailException;
import com.superbit.web.excep.ErrorCodeConstant;
import com.superbit.web.listener.ServiceBeanFactory;
import com.superbit.web.utils.CheckLoginMode;
import com.superbit.web.utils.CommonUtil;
import com.superbit.web.utils.JsonResponseUtil;
import com.superbit.web.utils.SessionUserUtil;
import com.superbit.web.utils.StringValidateUtil;

import net.sf.json.JSONObject;

/** @author  WangZhenwei 
  * @date 创建时间：2018年1月22日 下午6:10:52  
  * @descrip 用户登录处理的Controller层
  */
@Controller
@RequestMapping("/userLogin.act")
public class UserLoginController {

	private LoginService loginService;
	private UserRoleService userRoleService;
	
	/**
	 * @function 构造器注入service对象
	 */
	@PostConstruct
	private void init(){
		loginService = ServiceBeanFactory.getBean(LoginService.class);
		userRoleService = ServiceBeanFactory.getBean(UserRoleService.class);
	}
	
	
	
	/**
	 * 登录
	 * @param req
	 * @param resp
	 * @param account
	 * @param accountType
	 * @param password
	 * @return
	 */
	@ResponseBody
	@RequestMapping(params = "cmd=login")
	public String login(HttpServletRequest req, HttpServletResponse resp, final String account, final String accountType, final String password){
		
		
		// 1.验证账号和密码
		StringValidateUtil.validateNotEmpty(account, "account");
		int type = StringValidateUtil.strToInt(accountType, "accountType");
		StringValidateUtil.validateNotEmpty(password, "password");
		
		if(type == 1){
			boolean isEmail = StringValidateUtil.isEmail(account);
			if(! isEmail){
				throw new ParamInvalidException("email", "not email");
			}
		}else{
			boolean isPhone = StringValidateUtil.isPhone(account);
			if(! isPhone){
				throw new ParamInvalidException("mobile", " not mobile");
			}
		}
		
		// 获取用户远程IP
		String remoteIP = CommonUtil.getRemoteHost(req);
		// 判断登录方式
		int loginMode = UserStatusConstant.LOGIN_MODE_WEB;
		// 判断是否为移动端访问
		String userAgent = req.getHeader("USER-AGENT").toLowerCase();
		if(null == userAgent){
			userAgent = "";
		}
		boolean isHtml = CheckLoginMode.check(userAgent);
		// 判断是否为移动端访问
		if(isHtml){
			// 手机html
			loginMode = UserStatusConstant.LOGIN_MODE_PHONE_WEB;
		}else{
			loginMode = UserStatusConstant.LOGIN_MODE_WEB;
		}
		
		Map<String, Object> accessData = new ConcurrentHashMap<String, Object>();
		accessData.put("remoteIP", remoteIP);
		accessData.put("loginMode", (byte)loginMode);
		
		try {
			Map<String, Object> result = loginService.login(account, (byte)type, password, accessData);
			// 0未绑定 1已绑定
			String hasPhone = result.get("bindPhone").toString();
			if("0".equals(hasPhone)){
				// 没有手机，直接更新用户session信息
				this.updateUserSession(req, (int)result.get("userId"));
				result.clear();
				result.put("code", 0);				// 0 仅有密码验证
				result.put("message", "verifyPass");
				return JsonResponseUtil.buildSucessResonpe(result).toString();
			}else{
				// 开启双重认证（密码和验证码）有手机可以为手机验证或谷歌验证，将userid临时写入Session【此时页面不清楚要那种验证】
				HttpSession session = req.getSession();
				session.setAttribute("userId", result.get("userId"));
				if(null == result.get("googlePrivateKey") || result.get("googlePrivateKey").toString().length()<=0){
					// 此时认证手机
					result.clear();
					result.put("code", 1);				// 1 提示页面进入手机验证码验证页面
					result.put("message", "verifyPhone");
					//JsonResponseUtil.buildSucessResonpe(result);
				}else{
					// 此时谷歌认证
					result.clear();
					result.put("code", 2);				// 2 提示页面进入谷歌验证码验证页面
					result.put("message", "verifyGoogle");
					//JsonResponseUtil.buildSucessResonpe(result);
				}
				
			}
			return JsonResponseUtil.buildSucessResonpe(result).toString();
		} catch (BusinessException e) {			
			return JsonResponseUtil.buildBusiExcepResonpe(e).toString();			
		}
		// 
		// 2.账号或密码错误
		// 3.账号和密码正确
		//  3.1 谷歌验证（查看安全等级说明进行判断）
		//  3.2 手机验证（）
		//  3.3 不需要验证（邮箱账户且没有绑定谷歌、手机）
	}

	/**
	 * 更新用户session信息
	 * @param req
	 * @param resp
	 * @param object
	 * @return
	 */
	private Map<String, Object> updateUserSession(HttpServletRequest req, int userId) {
		// 获取用户基础信息对象
		UserBaseInfo userBaseInfo = loginService.getUserBaseInfo(userId);
		// 获取用户安全信息
		Map<String, Object> userSafeInfoMap = loginService.getUserSafeInfo(userId);
		// 获取用户活动对象信息
		UserActivityInfo userActivityInfo = loginService.getUserActivityInfo(userId);
		
		/*
		 * 组建Map
		 */
		Map<String, Object> map = new HashMap<String, Object>();
		// 用户基础信息
		map.put("id", userBaseInfo.getUserId());
		map.put("name", userBaseInfo.getNickname());
		map.put("email", userBaseInfo.getEmail());
		map.put("accountType", userBaseInfo.getAccountType());
		map.put("areaCode", userBaseInfo.getAreaCode());
		map.put("phone", this.replacePhone(userBaseInfo.getPhone()));
		map.put("registerDate", userBaseInfo.getRegisterDate());
		
		
		// 用户安全信息
		map.put("bindPhone", userSafeInfoMap.get("bindPhone"));
		map.put("pwdLevel", userSafeInfoMap.get("passwordLevel"));
		// 是否有资金密码
		boolean hasFundPassword = (boolean) userSafeInfoMap.get("hasFundPassword");
		map.put("hasFundPwd", hasFundPassword);
		// 是否实名认证
		map.put("authenStatus", userSafeInfoMap.get("authenStatus"));
		// 是否谷歌验证
		boolean hasGooglePrivateKey = (boolean) userSafeInfoMap.get("hasGooglePrivateKey");
		map.put("hasGoogleCode", hasGooglePrivateKey);
		byte securityLevel = (byte) userSafeInfoMap.get("securityLevel");
		if(securityLevel == 0){
			if(hasGooglePrivateKey && StringTools.isNotBlank(userBaseInfo.getPhone())){
				securityLevel = 3;
			}else if(hasGooglePrivateKey && !StringTools.isNotBlank(userBaseInfo.getPhone())){
				securityLevel = 2;
			}else if(!hasGooglePrivateKey && StringTools.isNotBlank(userBaseInfo.getPhone())){
				securityLevel = 1;
			}else{
				securityLevel = -1;
			}
		}
		// 账户安全级别
		map.put("securityLevel", securityLevel);
		map.put("loginAuthentication", userSafeInfoMap.get("loginAuthentication"));
		
		// 用户活动信息
		map.put("userLevel", userActivityInfo.getVIPLevel());
		map.put("score", userActivityInfo.getScore());
		
		// 用户角色
		String[] userRoles = userRoleService.getUserRoles(userId);
		if(userRoles != null && userRoles.length > 0){
			map.put("roles", userRoles);
		}
		
		// 存入session中
		SessionUserUtil.updateUserInfo(req.getSession(), map);
		return map;
	}

	/**
	 * 隐藏手机号码的部分信息
	 * @param phone
	 * @return
	 */
	private Object replacePhone(String phone) {
		if(phone == null || phone.equals("")){
			phone = "";
		}else if(phone.length()<8){
			phone = "********";
		}else{
			String pre = phone.substring(0, phone.length()-8);
			String post = phone.substring(phone.length()-4);
			phone = pre + "****" + post;
		}
		return phone;
	}
	
/*	*//**
	 * 设置登录认证
	 *//*
	@ResponseBody
	@RequestMapping(params = "cmd=setLoginAuthentication")
	public String setLoginAuthentication(HttpServletRequest req, final String loginAuthentication){
		int type = StringValidateUtil.strToInt(loginAuthentication, "loginAuthentication");
		
		JSONObject obj = new JSONObject();
		Map<String, Object> codeMap = new HashMap<>();
		
		Integer userId = SessionUserUtil.getLoginUserId(req.getSession());
		
		try {
			loginService.setLoginAuthentication(userId, type);
			obj.clear();
			obj.put("data", true);
			// 更新用户状态
			SessionUserUtil.sendUpdateUserMessage(userId, "loginAuthentication", type, req.getSession());
		} catch (BusinessException e) {
			codeMap.put("code", e.getErrorcode());
			codeMap.put("message", e.getMessage());
			obj.clear();
			obj.put("error", codeMap);
		}
		return obj.toString();
	}*/
	
	/**
	 * 校验登录认证时发送手机验证码
	 */
	@ResponseBody
	@RequestMapping(params = "cmd=checkLoginAuthenticationSendMessage")
	public String checkLoginAuthenticationSendMessage(HttpServletRequest req){
		//JSONObject obj = new JSONObject();
		//Map<String, Object> codeMap = new HashMap<String, Object>();
		String result = "";
		HttpSession session = req.getSession();
		Integer userId = (Integer) session.getAttribute("userId");
		if(userId == null){
			String errcode = ErrorCodeConstant.NOTLOGIN;
			String errmessage = "User not login";

			return JsonResponseUtil.buildNormalExcepResonpe(errcode, errmessage).toString();
		}
		
		try {
			loginService.checkLoginAuthenticationSendMessage(userId);
			result = JsonResponseUtil.buildSucessResonpe(true).toString();

		} catch (BusinessException e) {
			result = JsonResponseUtil.buildBusiExcepResonpe(e).toString();
		}
		return result;
	}
	
	/**
	 * 校验登录认证
	 */
	@ResponseBody
	@RequestMapping(params = "cmd=checkLoginAuthentication")
	public String checkLoginAuthentication(HttpServletRequest req, final String captcha, final String pageType){
		String result = "";
		// pageType 为0 仅有密码验证  为1  手机验证码  为2 谷歌验证码
		HttpSession session = req.getSession();
		Integer userId = (Integer) session.getAttribute("userId");
		if(userId == null){
			String errcode = ErrorCodeConstant.NOTLOGIN;
			String errmessage = "User not Login";
			return JsonResponseUtil.buildNormalExcepResonpe(errcode, errmessage).toString();
		}
		
		try {
			loginService.checkLoginAuthentication(userId, captcha, pageType);
			if(userId != null){
				session.removeAttribute("userId");
			}
			// 更新用户session信息
			this.updateUserSession(req, userId);
			
			//obj.clear();
			//obj.put("data", true);
			result = JsonResponseUtil.buildSucessResonpe(true).toString();
			//【认证通过跳转登陆后首页】
		} catch (BusinessException e) {

			result = JsonResponseUtil.buildBusiExcepResonpe(e).toString();
		}
		return result;
	}
	
	/**
	 * 用户登录时候忘记登录密码
	 */
	@ResponseBody
	@RequestMapping(params = "cmd=forgetLoginPassword")
	public String forgetLoginPassword(HttpServletRequest req, String account){
		String result = "";
		// 1.验证账户是手机号还是邮箱，去数据库查询是否存在账户
		HttpSession session = req.getSession();
		StringValidateUtil.validateNotEmpty(account, "account");
		boolean isEmail = StringValidateUtil.isEmail(account);
		boolean isPhone = StringValidateUtil.isPhone(account);
		if(isEmail || isPhone){
			// 邮箱账号的情况   手机账号的情况
			try {
				UserBaseInfo userBaseInfo = loginService.forgetLoginPassword(account);
				if(req.getSession().getAttribute("userId") != null){
					session.removeAttribute("userId");
				}
				// 账户真实有效且发送验证码的情况下更新用户Id到session
				Map<String, Object> map = new HashMap<String, Object>();
				// 用户基础信息
				map.put("id", userBaseInfo.getUserId());
				map.put("email", userBaseInfo.getEmail());
				map.put("areaCode", userBaseInfo.getAreaCode());
				map.put("phone", userBaseInfo.getPhone());
				SessionUserUtil.updateUserInfo(req.getSession(), map);
				
				result = JsonResponseUtil.buildSucessResonpe(true).toString();
			} catch (BusinessException e) {
				result = JsonResponseUtil.buildBusiExcepResonpe(e).toString();
				
			} catch (EmailFailException e) {
				result = JsonResponseUtil.buildNormalExcepResonpe("US626", "Email Send Fail!").toString();
				
			}				
		}else{
			// 无效账号
			throw new ParamInvalidException("account", " not validate account!");
		}
		// 2.存在账户向相应的手机号、或邮箱发送验证码		
		return result;
	}
	
	/**
	 * 用户登录时候忘记登录密码更改密码的请求
	 */
	@ResponseBody
	@RequestMapping(params = "cmd=applyChangeLoginPassword")
	public String applyChangeLoginPassword(HttpServletRequest req, String activeCode, String password, String rePassword){
		
		String result = "";
		// 1.验证用户输入项是否有效，验证码是否匹配
		boolean isEmpty = StringUtils.isEmpty(activeCode);
		if(isEmpty){
			throw new ParamInvalidException("activeCode", "not null");
		}
		boolean isBlank = StringUtils.isEmpty(activeCode.trim());
		if(isBlank){
			throw new ParamInvalidException("activeCode", "not blank");
		}
		// 2.密码是否符合规则
		// password = (String) req.getSession().getAttribute("password");
		if(!StringValidateUtil.isLoginPassword(password)){
			// 从session中去除密码
			req.getSession().removeAttribute("password");
			
			return JsonResponseUtil.buildNormalExcepResonpe("US616", "validate password").toString();
		}
		// 3.两次密码是否一致
		String repassword = (String) req.getSession().getAttribute("repassword");
		StringValidateUtil.validateNotEmpty(repassword, "repassword");
		if(!password.equals(repassword)){
			// 从session中移除确认密码
			req.getSession().removeAttribute("repassword");
			
			return JsonResponseUtil.buildNormalExcepResonpe("US617", "different password").toString();
		}
		
		// 验证session有效性，获取用户Id更新用户登录密码
		if(req.getSession(false)==null){
			throw new ParamInvalidException("session", "Session has been invalidated!");
		}else{
			// 从session中获取用户信息，更新数据库中的用户密码信息
			HttpSession session = req.getSession();
			Integer userId = (Integer) session.getAttribute("userId");
			String email = (String) session.getAttribute("email");
			String phone = (String) session.getAttribute("phone");
			String areaCode = (String) session.getAttribute("areaCode");
			Map<String, String> map = new HashMap<String, String>();
			map.put("phone", phone);
			map.put("areaCode", areaCode);
			map.put("email", email);
			// 调用业务逻辑实现
			try {
				loginService.changeLoginPassword(userId, activeCode, password, map);
				result = JsonResponseUtil.buildSucessResonpe(true).toString();
				//obj.clear();
				//obj.put("data", true);	
			} catch (BusinessException e) {
				//codeMap.put("code", e.getErrorcode());
				//codeMap.put("message", e.getMessage());
				//obj.clear();
				//obj.put("error", codeMap);
				result = JsonResponseUtil.buildBusiExcepResonpe(e).toString();
			}
		}
			
		// 2.若通过验证操作数据库更新用户登录密码
		return result;
	}
}
